package com.yonyou.ucf.mdd.isv.service;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.yonyou.iuap.context.InvocationInfoProxy;
import com.yonyou.iuap.metadata.core.model.businessobject.QueryBusinessObjectListReturn;
import com.yonyou.ucf.mdd.api.interfaces.rpc.IRuleApi;
import com.yonyou.ucf.mdd.common.constant.MddConstants;
import com.yonyou.ucf.mdd.common.model.rule.RuleContext;
import com.yonyou.ucf.mdd.common.model.rule.RuleExecuteResult;
import com.yonyou.ucf.mdd.common.model.uimeta.ui.Entity;
import com.yonyou.ucf.mdd.common.model.uimeta.ui.ViewModel;
import com.yonyou.ucf.mdd.common.utils.json.GsonHelper;
import com.yonyou.ucf.mdd.core.developer.tool.Tracker;
import com.yonyou.ucf.mdd.ext.base.tenant.Tenant;
import com.yonyou.ucf.mdd.ext.base.user.User;
import com.yonyou.ucf.mdd.ext.bill.dto.BillDataDto;
import com.yonyou.ucf.mdd.ext.bill.meta.biz.BillMetaBiz;
import com.yonyou.ucf.mdd.ext.bill.meta.service.BillMetaService;
import com.yonyou.ucf.mdd.ext.bpm.model.BpmRequestBody;
import com.yonyou.ucf.mdd.ext.bpm.model.BpmResponse;
import com.yonyou.ucf.mdd.ext.bpm.service.IProcessExService;
import com.yonyou.ucf.mdd.ext.bpm.service.ProcessStatusService;
import com.yonyou.ucf.mdd.ext.consts.Constants;
import com.yonyou.ucf.mdd.ext.core.AppContext;
import com.yonyou.ucf.mdd.ext.dao.meta.MetaDaoHelper;
import com.yonyou.ucf.mdd.ext.dao.sql.SqlHelper;
import com.yonyou.ucf.mdd.ext.datatransfer.IBillFormatService;
import com.yonyou.ucf.mdd.ext.dubbo.DubboReferenceUtils;
import com.yonyou.ucf.mdd.ext.exceptions.BusinessException;
import com.yonyou.ucf.mdd.ext.filter.util.StringUtil;
import com.yonyou.ucf.mdd.ext.i18n.utils.MddMultilingualUtil;
import com.yonyou.ucf.mdd.ext.meta.MetaAttributeUtils;
import com.yonyou.ucf.mdd.ext.model.BillContext;
import com.yonyou.ucf.mdd.ext.model.LoginUser;
import com.yonyou.ucf.mdd.ext.support.interfaces.IMddExtSupportService;
import com.yonyou.ucf.mdd.ext.util.BillContextUtils;
import com.yonyou.ucf.mdd.ext.util.Toolkit;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.yonyou.ucf.mdd.ext.utils.AdapterConvert;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.imeta.biz.base.Objectlizer;
import org.imeta.core.lang.BooleanUtils;
import org.imeta.core.model.Component;
import org.imeta.core.model.Property;
import org.imeta.orm.base.BizObject;
import org.imeta.orm.schema.QuerySchema;
import org.imeta.spring.base.MetaBeanFactory;
import org.imeta.spring.support.json.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import yonyou.bpm.rest.BpmRest;
import yonyou.bpm.rest.BpmRests;
import yonyou.bpm.rest.HistoryService;
import yonyou.bpm.rest.RepositoryService;
import yonyou.bpm.rest.RuntimeService;
import yonyou.bpm.rest.exception.RestException;
import yonyou.bpm.rest.param.BaseParam;
import yonyou.bpm.rest.request.AssignCheckParam;
import yonyou.bpm.rest.request.AssignInfo;
import yonyou.bpm.rest.request.RestVariable;
import yonyou.bpm.rest.request.category.CategoryQueryParam;
import yonyou.bpm.rest.request.category.CategoryResourceParam;
import yonyou.bpm.rest.request.form.FormFieldResourceParam;
import yonyou.bpm.rest.request.form.FormResourceParam;
import yonyou.bpm.rest.request.identity.BasicDataResourceParam;
import yonyou.bpm.rest.request.identity.OrgResourceParam;
import yonyou.bpm.rest.request.identity.TenantResourceParam;
import yonyou.bpm.rest.request.repository.CopyProcessDefinitionModel;
import yonyou.bpm.rest.request.repository.ProcessDefinitionModel;
import yonyou.bpm.rest.request.repository.ProcessDefinitionModelQuery;
import yonyou.bpm.rest.request.repository.ProcessDefinitionQueryParam;
import yonyou.bpm.rest.request.runtime.ProcessInstanceActionParam;
import yonyou.bpm.rest.request.runtime.ProcessInstanceStartParam;
import yonyou.bpm.rest.response.historic.HistoricProcessInstanceResponse;
import yonyou.bpm.rest.utils.StringUtils;

@Service("mddProcessService")
public class ISVProcessService {
    private static final Logger log = LoggerFactory.getLogger(ISVProcessService.class);
    private static final Logger logger = LoggerFactory.getLogger(ISVProcessService.class);
    private static final String ORG_ENTITYNAME = "aa.org.Org";
    private static final String TENANT_ENTITY = "base.tenant.Tenant";
    private static final String USER_ENTITY = "base.user.User";
    private static final String PROCESSKEY = "process_";
    private static final String BPMRESTURL = "/ubpm-web-rest/";
    private static final String BPMSSOURL = "/ubpm-web-approve/static/thirdpartylogin.html";
    @Value("${domain.iuap-apcom-workflow}")
    private String serverUrl;
    @Value("${bpmrest.tenant:#{null}}")
    private String tenant;
    @Value("${bpmrest.token:#{null}}")
    private String token;
    @Value("${bpmrest.appsource:#{null}}")
    private String appsource;
    @Value("${bpmrest.bpmsource:u8c}")
    private String BPMSOURCE;
    @Value("${bpmrest.appname:#{null}}")
    private String appname;
    @Value("${bpmrest.completeUrl:#{null}}")
    private String completeUrl;
    @Value("${bpmrest.frontUrl:#{null}}")
    private String frontUrl;
    @Value("${bpmrest.billtypeSubid:#{null}}")
    private String billtypeSubid;
    @Autowired
    private BillMetaBiz billMetaBiz;
    @Autowired
    private ProcessStatusService processStatusService;

    public ISVProcessService() {
    }

    public BpmRest bpmRestServices(String userId) {
        return this.bpmRestServices(userId, (String)null, (String)null);
    }

    public BpmRest bpmRestServices(String userId, String limitChildTenantId, String org) {
        return this.bpmRestServices((BillContext)null, userId, limitChildTenantId, org);
    }

    public BpmRest bpmRestServices(BillContext billContext, String userId, String limitChildTenantId, String org) {
        if (userId == null) {
            throw new IllegalArgumentException(String.format(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065346", "获取BpmRest时传入的userId[%s]是空"), userId));
        } else {
            BaseParam baseParam = new BaseParam();
            baseParam.setOperatorID(userId);
            baseParam.setServer(this.serverUrl + "/ubpm-web-rest/");
            baseParam.setTenant(this.tenant);
            String locale = InvocationInfoProxy.getLocale();
            if (StringUtil.isNotEmpty(locale)) {
                baseParam.setLanguage(locale);
            }

            if (Toolkit.isEmpty(this.appsource) && null != billContext) {
                baseParam.setSource(billContext.getSubid());
            } else {
                baseParam.setSource(this.appsource);
            }

            baseParam.setClientToken(this.token);
            baseParam.setTenantLimitId(limitChildTenantId);
            baseParam.setStartProcessOrg(org);
            baseParam.setYhtAccessToken(InvocationInfoProxy.getYhtAccessToken());
            logger.info("审批流支持日志 baseParam:{}", GsonHelper.ToJSon(baseParam));
            return BpmRests.getBpmRest(baseParam);
        }
    }

    public void init() throws Exception {
        User user = AppContext.getCurrentUser();
        String userId = user.getYhtUserId();
        if (null == userId) {
            userId = "admin";
        }

        String categoryId = this.saveCategory(userId, (String)null, (Map)null);
        this.initModelAndForm(userId, categoryId);
    }

    public void initTenant(Map<String, Object> paramMap) throws Exception {
        LoginUser user = AppContext.getCurrentUser();
        if (null == user && null != paramMap) {
            Map<String, Object> userData = (Map)paramMap.get("user");
            user = new LoginUser();
            user.putAll(Objectlizer.convert(userData, "base.user.User"));
        }

        this.registerInterface(user.getYhtUserId(), user.getYhtTenantId(), false);
        this.registerDetailAddress(user.getYhtUserId(), user.getYhtTenantId(), false);
        this.initTenantModelAndForm(user.getYhtUserId(), user.getYhtTenantId(), (Long)user.getTenant());
    }

    private void initModelAndForm(String userId, String categoryId) throws Exception {
        List<Map<String, String>> bills = SqlHelper.selectList("com.yonyou.ucf.mdd.ext.bpm.dao.findAllBpmBill", 0);
        if (null != bills && bills.size() > 0) {
            Iterator var4 = bills.iterator();

            while(var4.hasNext()) {
                Map<String, String> bill = (Map)var4.next();
                String modelId = this.saveProcessDefinition(userId, (String)null, (String)bill.get("billnum"), (String)bill.get("name"), categoryId);
                this.saveForm(userId, (String)null, modelId, (String)bill.get("billnum"), (String)bill.get("name"), (String)bill.get("fullname"), categoryId);
                this.updateBpmInitBill((String)bill.get("billnum"), 0L);
            }
        }

    }

    private void initTenantModelAndForm(String userId, String limitChildTenantId, Long tenant) throws Exception {
        List<Map<String, String>> bills = SqlHelper.selectList("com.yonyou.ucf.mdd.ext.bpm.dao.findAllBpmBill", tenant);
        if (null != bills && bills.size() > 0) {
            Iterator var5 = bills.iterator();

            while(var5.hasNext()) {
                Map<String, String> bill = (Map)var5.next();
                String categoryId = (String)bill.get("cSubId") + "." + (String)bill.get("billnum");
                this.initTenantOneModelAndForm(userId, limitChildTenantId, categoryId, tenant, bill);
            }
        }

    }

    private void initTenantOneModelAndForm(String userId, String limitChildTenantId, String categoryId, Long tenant, Map<String, String> bill) throws Exception, RestException {
        String processDefinitionKey = "process_" + (String)bill.get("billnum");
        String name = String.format(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065495", "%s流程"), bill.get("name"));
        String modelId = this.importProcessDefinition(userId, limitChildTenantId, processDefinitionKey, name, categoryId);
        this.saveForm(userId, limitChildTenantId, modelId, (String)bill.get("billnum"), (String)bill.get("name"), (String)bill.get("fullname"), categoryId);
        this.updateBpmInitBill((String)bill.get("billnum"), tenant);
    }

    private void updateBpmInitBill(String billnum, Long tenant) throws Exception {
        Map<String, Object> params = new HashMap();
        params.put("billno", billnum);
        params.put("tenant", tenant);
        SqlHelper.update("com.yonyou.ucf.mdd.ext.bpm.dao.updateBpmInitBill", params);
    }

    private ViewModel getCardSimpleVM(BillContext billContext) throws Exception {
        ViewModel cardSimpleVM = null;
        BillMetaService billMetaService = (BillMetaService)AppContext.getBean("billMetaService", BillMetaService.class);
        if (null != billMetaService) {
            if (StringUtils.isNotEmpty(billContext.getCardKey()) && !billContext.getCardKey().equals(billContext.getBillnum())) {
                cardSimpleVM = billMetaService.getSimpleVM(billContext.getCardKey(), (Long)null);
            } else {
                cardSimpleVM = billMetaService.getSimpleVM(billContext.getBillnum(), (Long)null);
            }
        } else {
            logger.error("billMetaService bean 为空");
        }

        return cardSimpleVM;
    }

    private Entity getMainEntity(ViewModel cardSimpleVM) {
        Entity vmMainEntity = null;
        if (null != cardSimpleVM) {
            Iterator var3 = cardSimpleVM.getEntities().iterator();

            while(var3.hasNext()) {
                Entity entity = (Entity)var3.next();
                if (entity.getIsMain()) {
                    vmMainEntity = entity;
                    break;
                }
            }
        }

        return vmMainEntity;
    }

    public void startBpm(BillContext billContext, List<BizObject> bills) throws Exception {
        this.startBpm(billContext, bills, (Map)null);
    }

    public void startBpm(BillContext billContext, List<BizObject> bills, Map<Object, BizObject> detailBills) throws Exception {
        LoginUser user = AppContext.getCurrentUser();
        ViewModel cardSimpleVM = this.getCardSimpleVM(billContext);
        BizObject formatBill = null;
        Iterator var7 = bills.iterator();

        while(var7.hasNext()) {
            BizObject bill = (BizObject)var7.next();
            if (null != detailBills && null != detailBills.get(bill.getId())) {
                formatBill = (BizObject)detailBills.get(bill.getId());
                Iterator var9 = bill.keySet().iterator();

                while(var9.hasNext()) {
                    String key = (String)var9.next();
                    Object value = bill.get(key);
                    if (!formatBill.containsKey(key)) {
                        formatBill.put(key, value);
                    }
                }
            }

            if (BooleanUtils.b((Boolean)bill.get("isWfControlled"))) {
                Object verifystate = bill.get("verifystate");
                Object status = bill.get(Constants.CONFIG_BILL_STATUS_FILED);
                this.processStatusService.checkStatusBeforeStartBpm(verifystate, status);
                this.processStatusService.setStatusWhenStartBpm(bill);
                if (null != formatBill) {
                    formatBill.set("isWfControlled", bill.get("isWfControlled"));
                    formatBill.set("verifystate", bill.get("verifystate"));
                    formatBill.set(Constants.CONFIG_BILL_STATUS_FILED, bill.get(Constants.CONFIG_BILL_STATUS_FILED));
                } else {
                    formatBill = (BizObject)com.yonyou.ucf.mdd.common.utils.Toolkit.deeplyCopyFromObject(bill);
                }

                MetaDaoHelper.update(billContext.getFullname(), bill);
                if (cardSimpleVM != null) {
                    IBillFormatService iBillFormatService = (IBillFormatService)AppContext.getBean("billFormatServiceImpl", IBillFormatService.class);
                    if (null != iBillFormatService) {
                        formatBill = iBillFormatService.formatBillData(formatBill, cardSimpleVM, this.getMainEntity(cardSimpleVM));
                    } else {
                        logger.error("IBillFormatService 接口实现类为空，未能处理格式化数据");
                    }
                } else {
                    logger.error("格式化处理流程参数 异常， viewmodel 为空");
                }

                List<RestVariable> taskVariables = this.prepareVariables(formatBill);
                // mdd-bpm中补充单据类型 --yanx于2020/6/16注释
                String billTypeId = bill.get("billTypeId");
                String businessKey = null;
                //新架构审批流billTypeId用appsource和业务对象编码拼接
                Boolean isNewArch = AppContext.getCurrentUser().getNewArch(); //是否启用新架构
                if(isNewArch) {
                    String bizObjCode = billContext.getMddBoId();
                    billTypeId = appsource + "." + bizObjCode;
                    businessKey = bizObjCode+ "_" + bill.get("id");
                }else {
                    if (null == billTypeId) {
                        String billNum = billContext.getBillnum();
                        String cardKey = billContext.getCardKey();
                        if (org.apache.commons.lang.StringUtils.isNotEmpty(cardKey) && !cardKey.equals(billNum)) {// 列表批审的单据类型用cardKey
                            billTypeId = cardKey;
                        } else {
                            billTypeId = billNum;
                        }

                        if (org.apache.commons.lang.StringUtils.isNotEmpty(appsource)) {
                            billTypeId = appsource + "." + billTypeId;
                        }
                    }
                    businessKey = billContext.getBillnum() + "_" + bill.get("id");
                }
                String categoryId = billTypeId;
                String procInstName = this.getCode(billContext, formatBill);
                String masterOrg = this.getMasterOrg(billContext, formatBill);
                HistoricProcessInstanceResponse response = null;

                RestVariable rvInitiatorOrg = new RestVariable();
                rvInitiatorOrg.setName("initiatorOrg");
                rvInitiatorOrg.setValue(masterOrg);// 20211221 发起组织，增加传递参数， since 3.0.9-SNAPSHOT

                //增加业务对象相关参数 20220701
                setBizObjNewArchParams(billContext, taskVariables);
                // 增加serviceCode
                setServiceCodeWhenStart(businessKey, taskVariables);

                try {
                    response = this.startProcessByKey(billContext, user.getYhtUserId(), categoryId, procInstName, businessKey, taskVariables, user.getYhtTenantId(), masterOrg);
                    logger.info("ProcessService  BPM START , RESPONSE: " + response);
                } catch (Exception var18) {
                    throw var18;
                }
            }
        }

    }

    /**
     * @Description 增加业务对象相关参数传给流程服务
     **/
    public void setBizObjNewArchParams(BillContext billContext, List<RestVariable> taskVariables) {
        try {
            Boolean isNewArch = AppContext.getCurrentUser().getNewArch(); //启用新架构
            String bizObjCode = billContext.getMddBoId();
            String yhtTenantId = AppContext.getYhtTenantId();
            if(null != isNewArch && isNewArch && null != bizObjCode){
                IMddExtSupportService mddExtSupportService = AppContext.getBean(IMddExtSupportService.class);
                if(null != mddExtSupportService){
                    QueryBusinessObjectListReturn queryBusinessObjectListReturn = mddExtSupportService.queryBizObjByCode(yhtTenantId, bizObjCode);
                    if(null != queryBusinessObjectListReturn){
                        taskVariables.add(createRestVariable("busiObjCode", queryBusinessObjectListReturn.getCode()));
                        taskVariables.add(createRestVariable("busiObjUri", queryBusinessObjectListReturn.getUri()));
                        taskVariables.add(createRestVariable("domain", queryBusinessObjectListReturn.getDomain()));
                    }
                }
            }
        } catch (Exception e) {
            logger.error("setBizObjNewArchParams 增加业务对象相关参数传给流程服务 发生异常{}", e);
        }
    }

    /**
     * @Description 创建流程参数对象
     **/
    private RestVariable createRestVariable(String name, Object value){
        RestVariable restVar = new RestVariable();
        restVar.setName(name);
        restVar.setValue(value);
        return restVar;
    }

    public void setServiceCodeWhenStart(String businessKey, List<RestVariable> taskVariables){
        Object serviceCode = AppContext.getThreadContext(MddConstants.PARAM_SERVICE_CODE);
        Tracker.recordLogClues(this.getClass().getName(), "setServiceCodeWhenStart", String.format("流程提交设置serviceCode, 当前单据businessKey: %s, 当前serviceCode: %s", businessKey, serviceCode));
        if(null != serviceCode){
            taskVariables.add(createRestVariable("mddServiceCode", serviceCode));
        } else {
            logger.error("流程提交 serviceCode 为空, businessKey" + businessKey);
        }
    }


    public List<Map> getAuditorsNew(List<String> processBusinessKeyList, String billnum) throws Exception {
        List<Map> auditorInfos = new ArrayList();
        HistoryService historyservice = this.bpmRestServices().getHistoryService();
        long startTime = System.currentTimeMillis();
        log.info("getAuditorsNew ## ", startTime);
        Object restResult = historyservice.getHistoricProcessInstancesAssignee(processBusinessKeyList);
        JsonNode responseNode = null;
        if (restResult instanceof JsonNode) {
            responseNode = (JsonNode)restResult;
        } else {
            if (!(restResult instanceof String) || null == restResult) {
                logger.error("getAuditors ## 返回结果不正确 JsonNode 请尽快联系审批流开发进行排查！！ {}", restResult);
                throw new Exception("云审批服务查询返回结果不正确： " + restResult);
            }

            ObjectMapper objectMapper = new ObjectMapper();
            responseNode = objectMapper.readTree(restResult.toString());
        }

        if (responseNode != null && null != responseNode.get("data")) {
            JsonNode data = responseNode.get("data");
            if (data.isArray()) {
                Iterator list = data.iterator();

                while(true) {
                    String billid;
                    JsonNode firstTask;
                    do {
                        label64:
                        do {
                            while(list.hasNext()) {
                                JsonNode node = (JsonNode)list.next();
                                billid = null;
                                if (null != node.get("businessKey")) {
                                    String businessKey = node.get("businessKey").asText();
                                    if (businessKey.contains(billnum + "_")) {
                                        billid = businessKey.substring(billnum.length() + 1);
                                    }
                                }

                                JsonNode tasks = node.get("historicTasks");
                                if (tasks != null && tasks.isArray()) {
                                    firstTask = ((ArrayNode)tasks).get(0);
                                    continue label64;
                                }

                                logger.error("tasks 为空或不是数组，直接跳转下一次循环 " + tasks);
                            }

                            return auditorInfos;
                        } while(null == firstTask);
                    } while(null == firstTask.get("assigneeParticipant"));

                    JsonNode assignee = firstTask.get("assigneeParticipant");
                    String name = null == assignee.get("name") ? null : assignee.get("name").asText();
                    String id = null == assignee.get("id") ? null : assignee.get("id").asText();
                    boolean billidExist = false;
                    if (CollectionUtils.isNotEmpty(auditorInfos)) {
                        Iterator var19 = auditorInfos.iterator();

                        while(var19.hasNext()) {
                            Map<String, String> auditorInfo = (Map)var19.next();
                            if (((String)auditorInfo.get("billid")).equals(billid)) {
                                billidExist = true;
                                auditorInfo.put("id", (String)auditorInfo.get("id") + "," + id);
                                auditorInfo.put("name", (String)auditorInfo.get("name") + "," + name);
                                break;
                            }
                        }
                    }

                    if (!billidExist) {
                        Map<String, String> auditorInfo = new HashMap();
                        auditorInfo.put("billid", billid);
                        auditorInfo.put("id", id);
                        auditorInfo.put("name", name);
                        auditorInfos.add(auditorInfo);
                    }
                }
            } else {
                return auditorInfos;
            }
        } else if (null != responseNode.get("errcode") && 0 != responseNode.get("errcode").intValue()) {
            throw new BusinessException("获取流程审批人异常, 接口返回结果: " + responseNode.toString());
        } else {
            throw new BusinessException("获取流程审批人, 接口返回结果为空: " + responseNode);
        }
    }

    public BpmRest bpmRestServices() throws Exception {
        LoginUser user = AppContext.getCurrentUser();
        String userId = user.getYhtUserId() != null ? user.getYhtUserId().toString() : "";
        String limitTenantId = user.getYTenantId() != null ? user.getYTenantId().toString() : null;
        String orgId = user.getOrgId();
        return this.bpmRestServices(userId, limitTenantId, orgId);
    }

    public void updateBpmProcess(BillContext billContext, BizObject bill) throws Exception {
        LoginUser user = AppContext.getCurrentUser();
        if (BooleanUtils.b((Boolean)bill.get("isWfControlled"))) {
            List taskVariables = null;

            try {
                BizObject formatBill = (BizObject)com.yonyou.ucf.mdd.common.utils.Toolkit.deeplyCopyFromObject(bill);
                ViewModel cardSimpleVM = this.getCardSimpleVM(billContext);
                Entity vmMainEntity = this.getMainEntity(cardSimpleVM);
                if (vmMainEntity != null) {
                    IBillFormatService iBillFormatService = (IBillFormatService)AppContext.getBean("billFormatServiceImpl", IBillFormatService.class);
                    if (null != iBillFormatService) {
                        formatBill = iBillFormatService.formatBillData(formatBill, cardSimpleVM, vmMainEntity);
                    } else {
                        logger.error("IBillFormatService 接口实现类为空，未能处理格式化数据");
                    }
                } else {
                    logger.error("格式化处理流程参数 异常， viewmodel 为空");
                }

                taskVariables = this.prepareVariables(formatBill);
            } catch (Exception var9) {
                logger.error("格式化处理流程参数 异常，", var9);
                taskVariables = this.prepareVariables(bill);
            }

            String businessKey = billContext.getBillnum() + "_" + bill.get("id");
            HistoricProcessInstanceResponse response = this.updateProcessVariables(billContext, user.getYhtUserId(), businessKey, taskVariables, user.getYhtTenantId(), user.getOrgId());
            if (logger.isDebugEnabled()) {
                logger.debug(response.toString());
            }

            String instanceId = response.getId();
            logger.debug(instanceId);
        }
    }

    private HistoricProcessInstanceResponse updateProcessVariables(BillContext billContext, String userId, String businessKey, List<RestVariable> variables, String limitChildTenantId, String org) throws RestException {
        if (logger.isInfoEnabled()) {
            logger.info("更新流程。流程变量数据={}", GsonHelper.ToJSon(variables));
        }

        RuntimeService rt = this.bpmRestServices(billContext, userId, limitChildTenantId, org).getRuntimeService();
        ProcessInstanceActionParam processInstanceActionParam = new ProcessInstanceActionParam();
        processInstanceActionParam.setVariables(variables);
        ObjectNode node = (ObjectNode)rt.updateProcessVariablesByBusinessKey(businessKey, processInstanceActionParam);
        HistoricProcessInstanceResponse resp = (HistoricProcessInstanceResponse)JSON.parseObject(node.toString(), HistoricProcessInstanceResponse.class);
        return resp;
    }

    public Object getProcessDefinitionByBillnum(String billnum) throws Exception {
        LoginUser user = AppContext.getCurrentUser();
        String tenantId = user.getYhtTenantId();
        String userId = user.getYhtUserId();
        Object result = this.getProcessDefinitionByKey(userId, tenantId, billnum);
        return result;
    }

    public String getProcessDefinition(String billnum) throws Exception {
        LoginUser user = AppContext.getCurrentUser();
        String tenantId = user.getYhtTenantId();
        String userId = user.getYhtUserId();
        String modelId = this.getProcessDefinitionIdByKey(userId, tenantId, billnum);
        return String.format("%s%s?source=%s&modelId=%s&organizationId=%s&page=flow&usercode=user_code&userid=%s&appsource=%s&locale=zh_CN", this.serverUrl, "/ubpm-web-approve/static/thirdpartylogin.html", this.BPMSOURCE, modelId, tenantId, userId, this.appsource);
    }

    private List<RestVariable> prepareVariables(BizObject bill) {
        return this.prepareVariablesSingle(bill, (String)null);
    }

    private List<RestVariable> prepareVariablesSingle(BizObject bill, String roleA) {
        List<RestVariable> taskVariables = new ArrayList();
        Iterator var4 = bill.entrySet().iterator();

        while(true) {
            while(true) {
                Entry entry;
                do {
                    do {
                        if (!var4.hasNext()) {
                            return taskVariables;
                        }

                        entry = (Entry)var4.next();
                    } while(((String)entry.getKey()).startsWith("_"));
                } while(null == entry.getValue());

                Object val = entry.getValue();
                String name = (String)entry.getKey();
                List valList;
                if (!(val instanceof List)) {
                    valList = this.buildData(bill, roleA, entry, val);
                    taskVariables.addAll(valList);
                } else {
                    valList = (List)val;
                    if (CollectionUtils.isNotEmpty(valList) && valList.size() == 1) {
                        Object val2 = valList.get(0);
                        if (null != val2 && val2 instanceof BizObject) {
                            BizObject bizObject = (BizObject)val2;
                            List<RestVariable> restVariableList = this.prepareVariablesSingle(bizObject, name);
                            taskVariables.addAll(restVariableList);
                        }
                    } else {
                        RestVariable v2 = new RestVariable();
                        v2.setName(name);
                        v2.setValue(val);
                        taskVariables.add(v2);
                    }
                }
            }
        }
    }

    private List<RestVariable> buildData(BizObject bill, String roleA, Entry<String, Object> entry, Object val) {
        List<RestVariable> taskVariables = new ArrayList();
        RestVariable v2 = new RestVariable();
        String name = (String)entry.getKey();
        if (StringUtil.isNotEmpty(roleA)) {
            name = roleA + "." + name;
        }

        v2.setName(name);
        if (val instanceof Date) {
            v2.setValue(this.getISO8601Timestamp((Date)entry.getValue()));
            v2.setType("date");
            taskVariables.add(v2);
        } else if (val instanceof BizObject && ((BizObject)val).containsKey("_parent")) {
            BizObject childMap = (BizObject)val;
            Object parent = childMap.get("_parent");
            if (null != parent && parent.equals(bill)) {
                List<RestVariable> taskVariables4Child = this.prepareVariablesSingle(childMap, name);
                if (CollectionUtils.isNotEmpty(taskVariables4Child)) {
                    taskVariables.addAll(taskVariables4Child);
                }
            }
        } else {
            v2.setValue(val);
            taskVariables.add(v2);
        }

        return taskVariables;
    }

    private String getISO8601Timestamp(Date date) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        String nowAsISO = df.format(date);
        return nowAsISO;
    }

    private String saveCategory(String userId, String limitChildTenantId, Map<String, String> bill) throws Exception {
        CategoryResourceParam categroyReourceParam = new CategoryResourceParam();
        String code = "default";
        if (null != limitChildTenantId && null != bill) {
            code = String.format("%s%s_%s", "process_", bill.get("billnum"), limitChildTenantId);
        }

        String name = String.format(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065495", "%s流程"), bill.get("name"));
        categroyReourceParam.setId(code);
        categroyReourceParam.setCode(code);
        categroyReourceParam.setName(name);
        categroyReourceParam.setSource(this.appsource);
        JsonNode responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getCategoryService().insertCategory(categroyReourceParam);
        if (null != responseNode && logger.isDebugEnabled()) {
            logger.debug(responseNode.toString());
        }

        if (null != responseNode.get("errcode") && 0 != responseNode.get("errcode").intValue()) {
            CategoryQueryParam categoryQueryParam = new CategoryQueryParam();
            categoryQueryParam.setCategoryCode(code);
            JsonNode responseNode2 = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getCategoryService().getCategories(categoryQueryParam);
            if (null != responseNode2.get("data") && responseNode2.get("data").size() > 0) {
                return responseNode2.get("data").get(0).get("id").textValue();
            } else {
                throw new BusinessException(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065683", "未找到分类"));
            }
        } else {
            return responseNode.get("id").textValue();
        }
    }

    private String handleResult(JsonNode responseNode) throws Exception {
        logger.info("审批流支持日志 handleResult:{}", JsonUtils.toJson(responseNode));
        if (null != responseNode.get("errcode") && 0 != responseNode.get("errcode").intValue()) {
            logger.error("error:{}", responseNode);
            throw new BusinessException(responseNode.get("errmsg").textValue());
        } else if (null == responseNode.get("id")) {
            if (null != responseNode.get("data") && responseNode.get("data").size() > 0) {
                return null != responseNode.get("data").get(0) && null != responseNode.get("data").get(0).get("id") ? responseNode.get("data").get(0).get("id").textValue() : null;
            } else {
                return null;
            }
        } else {
            return responseNode.get("id").textValue();
        }
    }

    private void saveTenant(String userId, Tenant tenant) throws Exception {
        TenantResourceParam tenantResourceParam = new TenantResourceParam();
        tenantResourceParam.setCode(this.appsource);
        tenantResourceParam.setName(this.appname);
        tenantResourceParam.setId(tenant.getTenantCenter());
        JsonNode responseNode = (JsonNode)this.bpmRestServices(userId).getIdentityService().saveTenant(tenantResourceParam);
        this.handleResult(responseNode);
    }

    private void saveOrg(User user, String limitChildTenantId) throws Exception {
        QuerySchema schema = QuerySchema.create().addSelect("id,code,name,parent,parent.code as parentcode");
        List<Map<String, Object>> orgs = MetaDaoHelper.query("aa.org.Org", schema, Constants.BASEDOMAIN);
        if (null != orgs && orgs.size() > 0) {
            OrgResourceParam[] orgResourceParams = new OrgResourceParam[orgs.size()];
            int i = 0;

            for(Iterator var7 = orgs.iterator(); var7.hasNext(); ++i) {
                Map<String, Object> org = (Map)var7.next();
                OrgResourceParam orgResourceParam = new OrgResourceParam();
                orgResourceParam.setCode((String)org.get("code"));
                orgResourceParam.setName((String)org.get("name"));
                orgResourceParam.setId(String.valueOf(org.get("id")));
                orgResourceParam.setParentCode((String)org.get("parentcode"));
                orgResourceParam.setParent(String.valueOf(org.get("parent")));
                orgResourceParam.setTenantId(limitChildTenantId);
                orgResourceParam.setRevision(0);
                orgResourceParams[i] = orgResourceParam;
            }

            JsonNode responseNode = (JsonNode)this.bpmRestServices(user.getYhtUserId(), limitChildTenantId, (String)null).getIdentityService().saveOrgs(orgResourceParams);
            if (null != responseNode && logger.isDebugEnabled()) {
                logger.debug(responseNode.toString());
            }
        }

    }

    private String saveProcessDefinition(String userId, String limitChildTenantId, String billnum, String name, String categoryId) throws Exception {
        ProcessDefinitionModel ProcessDefinitionModel = new ProcessDefinitionModel();
        ProcessDefinitionModel.setKey("process_" + billnum);
        ProcessDefinitionModel.setCategory(categoryId);
        ProcessDefinitionModel.setName(String.format(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065495", "%s流程"), name));
        ProcessDefinitionModel.setTenantId(limitChildTenantId);
        JsonNode responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getRepositoryService().createProcessDefinitionModel(ProcessDefinitionModel);
        if (null != responseNode && logger.isDebugEnabled()) {
            logger.debug(responseNode.toString());
        }

        return this.handleResult(responseNode);
    }

    private void saveForm(String userId, String limitChildTenantId, String modelId, String billnum, String name, String fullname, String categoryId) throws RestException {
        FormResourceParam formResourceParam = new FormResourceParam();
        formResourceParam.setModelId(modelId);
        formResourceParam.setTitle(name);
        formResourceParam.setCode(billnum);
        formResourceParam.setDescription(name);
        formResourceParam.setCategory(categoryId);
        JsonNode responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getFormService().saveForm(formResourceParam);
        if (null != responseNode && logger.isDebugEnabled()) {
            logger.debug(responseNode.toString());
        }

        this.saveFormField(userId, responseNode.get("id").textValue(), limitChildTenantId, modelId, fullname);
    }

    private void saveFormField(String userId, String billnum, String limitChildTenantId, String modelId, String fullname) throws RestException {
        org.imeta.core.model.Entity entity = MetaBeanFactory.getMetaRepository().entity(fullname);
        List<FormFieldResourceParam> formFieldResourceParams = new ArrayList();
        if (entity != null && !CollectionUtils.isEmpty(entity.attributes())) {
            Iterator var8 = entity.attributes().iterator();

            while(var8.hasNext()) {
                Property attr = (Property)var8.next();
                new FormFieldResourceParam();
                FormFieldResourceParam formFieldResourceParam = new FormFieldResourceParam();
                formFieldResourceParam.setFormId(billnum);
                formFieldResourceParam.setName((String)attr.get("title"));
                formFieldResourceParam.setTypeName("string");
                formFieldResourceParam.setCode((String)attr.get("name"));
                formFieldResourceParam.setModelId(modelId);
                formFieldResourceParams.add(formFieldResourceParam);
            }
        }

        JsonNode responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getFormService().saveFormFields(formFieldResourceParams);
        if (null != responseNode && logger.isDebugEnabled()) {
            logger.debug(responseNode.toString());
        }

    }

    public void registerInterface(boolean isUpdate) throws Exception {
        LoginUser user = AppContext.getCurrentUser();
        this.registerInterface(user.getYhtUserId(), user.getYhtTenantId(), isUpdate);
    }

    private Tenant getTenant(User user) throws Exception {
        Tenant tenant = (Tenant)MetaDaoHelper.findById("base.tenant.Tenant", (Long)user.getTenant(), Constants.BASEDOMAIN);
        if (null != tenant && !Toolkit.isEmpty(tenant.getTenantCenter())) {
            return tenant;
        } else {
            throw new BusinessException(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065715", "租户信息错误"));
        }
    }

    private void registerInterface(String userId, String limitChildTenantId, boolean isUpdate) throws Exception {
        BasicDataResourceParam basicDataResouceParam = new BasicDataResourceParam();
        basicDataResouceParam.setCode("complete");
        basicDataResouceParam.setName("终审");
        basicDataResouceParam.setType("process_listener");
        basicDataResouceParam.setTenantId(limitChildTenantId);
        basicDataResouceParam.setUrl(this.completeUrl + "/bpm/complete");
        basicDataResouceParam.setToken("yxybpm");
        basicDataResouceParam.setSource(this.BPMSOURCE);
        JsonNode responseNode = null;
        if (isUpdate) {
            responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getIdentityService().updateBasicData(basicDataResouceParam);
        } else {
            responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getIdentityService().insertBasicData(basicDataResouceParam);
        }

        if (null != responseNode && logger.isDebugEnabled()) {
            logger.debug(responseNode.toString());
        }

        this.handleResult(responseNode);
    }

    private void registerDetailAddress(String userId, String limitChildTenantId, boolean isUpdate) throws Exception {
        BasicDataResourceParam basicDataResouceParam = new BasicDataResourceParam();
        basicDataResouceParam.setCode("detail");
        basicDataResouceParam.setName("详情");
        basicDataResouceParam.setType("business_url");
        basicDataResouceParam.setTenantId(limitChildTenantId);
        basicDataResouceParam.setUrl(this.frontUrl + "/meta/voucher/");
        basicDataResouceParam.setToken("yxybpm");
        basicDataResouceParam.setSource(this.BPMSOURCE);
        JsonNode responseNode = null;
        if (isUpdate) {
            responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getIdentityService().updateBasicData(basicDataResouceParam);
        } else {
            responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getIdentityService().insertBasicData(basicDataResouceParam);
        }

        if (null != responseNode && logger.isDebugEnabled()) {
            logger.debug(responseNode.toString());
        }

        this.handleResult(responseNode);
    }

    private HistoricProcessInstanceResponse startProcessByKey(BillContext billContext, String userId, String categoryId, String procInstName, String businessKey, List<RestVariable> variables, String limitChildTenantId, String org) throws RestException {
        if (logger.isInfoEnabled()) {
            logger.info("启动流程。流程变量数据={}", GsonHelper.ToJSon(variables));
        }

        RuntimeService rt = this.bpmRestServices(billContext, userId, limitChildTenantId, org).getRuntimeService();
        ProcessInstanceStartParam parm = new ProcessInstanceStartParam();
        parm.setCategory(categoryId);
        String subId = Toolkit.isEmpty(this.billtypeSubid) ? billContext.getSubid() : this.billtypeSubid;
        String cardBillNo = StringUtils.isBlank(billContext.getCardKey()) ? billContext.getBillnum() : billContext.getCardKey();
        if (null != billContext) {
            parm.setBillTypeId(subId + "." + cardBillNo);
        }

        parm.setVariables(variables);
        parm.setProcessInstanceName(procInstName);
        parm.setCheckBusinessKeyExist(true);
        parm.setBusinessKey(businessKey);
        Object assignInfo = billContext.getCusMapValue("assignInfo");
        if (null != assignInfo) {
            parm.setAssignInfo((AssignInfo)assignInfo);
        }

        ObjectNode node = (ObjectNode)rt.startProcess(parm);
        String errorCode = node.get("errcode") == null ? null : node.get("errcode").toString();
        if (errorCode != null && !"0".equals(errorCode)) {
            logger.error("启动流程。结果数据={}", node.toString());
            throw new BusinessException("启动流程异常, 接口返回结果: " + node.toString());
        } else {
            HistoricProcessInstanceResponse resp = (HistoricProcessInstanceResponse)JSON.parseObject(node.toString(), HistoricProcessInstanceResponse.class);
            if (logger.isInfoEnabled()) {
                logger.info("启动流程。结果数据={}", GsonHelper.ToJSon(resp));
            }

            return resp;
        }
    }

    private String importProcessDefinition(String userId, String limitChildTenantId, String processDefinitionKey, String name, String categoryId) throws Exception {
        InputStream in = this.getProcessDefinitionResourceDataByKey(userId, (String)null, processDefinitionKey);
        return this.createModelByBPMNFile(userId, limitChildTenantId, in, processDefinitionKey, name, categoryId);
    }

    private String getProcessDefinitionIdByKey(String userId, String limitChildTenantId, String billnum) throws Exception {
        JsonNode responseNode = this.getProcessDefinitionByKey(userId, limitChildTenantId, billnum);
        return this.handleResult(responseNode);
    }

    private JsonNode getProcessDefinitionByKey(String userId, String limitChildTenantId, String billnum) throws Exception {
        String processDefinitionKey = "process_" + billnum + "_" + limitChildTenantId;
        ProcessDefinitionModelQuery processDefinitionModelQuery = new ProcessDefinitionModelQuery();
        processDefinitionModelQuery.setKey(processDefinitionKey);
        JsonNode responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getRepositoryService().getProcessDefinitionModels(processDefinitionModelQuery);
        return responseNode;
    }

    private InputStream getProcessDefinitionResourceDataByKey(String userId, String limitChildTenantId, String processDefinitionKey) throws Exception {
        byte[] results = (byte[])this.bpmRestServices(userId, limitChildTenantId, (String)null).getRepositoryService().getProcessDefinitionResourceDataByKey(processDefinitionKey);
        InputStream inputStream = new ByteArrayInputStream(results);
        return inputStream;
    }

    private String createModelByBPMNFile(String userId, String limitChildTenantId, InputStream inputStream, String processDefinitionKey, String name, String categoryId) throws Exception {
        CopyProcessDefinitionModel model = new CopyProcessDefinitionModel();
        processDefinitionKey = processDefinitionKey + "_" + limitChildTenantId;
        model.setKey(processDefinitionKey);
        model.setName(name);
        model.setCategory(categoryId);
        JsonNode responseNode = (JsonNode)this.bpmRestServices(userId, limitChildTenantId, (String)null).getRepositoryService().createModelByBPMNFile(inputStream, processDefinitionKey, model);
        inputStream.close();
        return this.handleResult(responseNode);
    }

    public void cancelBpm(BillContext billContext, List<BizObject> bills) throws Exception {
        if ("delete".equalsIgnoreCase(billContext.getAction())) {
            LoginUser user = AppContext.getCurrentUser();
            String limitChildTenantId = user.getYhtTenantId();
            Iterator var5 = bills.iterator();

            while(var5.hasNext()) {
                BizObject bill = (BizObject)var5.next();
                String cardKey = billContext.getCardKey();
                String billnum = StringUtils.isNoneBlank(new CharSequence[]{cardKey}) ? cardKey : billContext.getBillnum();
                String businessKey = billnum + "_" + bill.get("id");
                String org = null;
                HistoryService historyService = this.bpmRestServices(billContext, user.getYhtUserId(), limitChildTenantId, (String)org).getHistoryService();
                historyService.deleteHistoricProcessInstanceWithAllByBusinessKey(businessKey, false);
            }

        }
    }

    public String bpmComplete(BpmRequestBody params) {
        logger.info("bpmComplete param:{}", GsonHelper.ToJSon(params));

        try {
            BillDataDto dto = this.checkCompleteIdentity(params);
            BillContext billContext = BillContextUtils.getBillContext(dto.getBillnum());
            if (null == billContext) {
                throw new BusinessException(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065065", "没有对应表单"));
            } else {
                org.imeta.core.model.Entity entity = MetaDaoHelper.getEntity(billContext.getFullname());
                Component component = (Component)entity.owner();
                String domain = component.domain();
                billContext.setAction("audit");
                billContext.setbRowAuthControl(true);
                billContext.setbRowAuthControl(true);
                if (null != params.getEventName()) {
                    billContext.setDeleteReason(params.getEventName());
                } else {
                    billContext.setDeleteReason(params.getDeleteReason());
                }

                if (null != billContext.getDeleteReason()) {
                    if ("withdraw".equalsIgnoreCase(billContext.getDeleteReason())) {
                        billContext.setAction("unaudit");
                    } else {
                        billContext.setAction("deleteBpm");
                    }
                }

                billContext.setTransaction(true);
                Map<String, Object> externalMap = null;
                if (dto.getExternalData() != null && dto.getExternalData() instanceof Map) {
                    externalMap = (Map)dto.getExternalData();
                } else {
                    externalMap = new HashMap();
                }

                ((Map)externalMap).put("isBpm", true);
                dto.setExternalData(externalMap);
                RuleExecuteResult result = null;

                try {
                    IRuleApi ruleApi = (IRuleApi)DubboReferenceUtils.getDubboService(IRuleApi.class, domain, (String)null);
                    RuleContext ruleContext = new RuleContext();
                    ruleContext.setBillContext(billContext);
                    result = ruleApi.pureExecuteRule(ruleContext, AdapterConvert.convert2BaseReqDto(dto));
                } catch (Exception var11) {
                    throw var11;
                }

                if (result == null) {
                    throw new BusinessException("result is null");
                } else if (result.getMsgCode() != 1) {
                    throw new BusinessException(result.getMessage());
                } else {
                    return BpmResponse.success();
                }
            }
        } catch (Exception var12) {
            logger.error("bpm complete error: ", var12);
            return BpmResponse.fail(var12.getMessage());
        }
    }

    private BillDataDto checkCompleteIdentity(BpmRequestBody params) throws Exception {
        if (!Toolkit.isEmpty(params.getYht_access_token())) {
            //AppContext.setToken(params.getYht_access_token());
            //AppContext.getCurrentUserByReLogin(params.getYht_access_token());
        } else {
            if (Toolkit.isEmpty(params.getUserId())) {
                throw new BusinessException(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065308", "没有用户信息"));
            }

            if (Toolkit.isEmpty(params.getTenantId())) {
                throw new BusinessException(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065684", "没有租户信息"));
            }

            String yhtTenantId = "";
            if (null != params.getTenantId()) {
                yhtTenantId = params.getTenantId().split("_")[0];
            }

            AppContext.getYhtCurrentUser(params.getUserId(), yhtTenantId);
        }

        BillDataDto dto = new BillDataDto();
        if (Toolkit.isEmpty(params.getBusinessKey())) {
            throw new BusinessException(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065613", "没有业务号"));
        } else {
            String businessKey = params.getBusinessKey();
            int pos = businessKey.lastIndexOf("_");
            String billnum = "";
            String id = null;
            if (pos > 0) {
                billnum = businessKey.substring(0, pos);
                id = businessKey.substring(pos + 1);
                dto.setBillnum(billnum);
                String datas = String.format("[{\"id\":%s}]", id);
                dto.setData(datas);
                return dto;
            } else {
                throw new BusinessException(MddMultilingualUtil.getFWMessage("P_YS_FW-PUB_MDD-BACK_0001065172", "业务单据错误"));
            }
        }
    }

    public void withdraw(BillContext billContext, List<BizObject> bills) throws Exception {
        LoginUser user = AppContext.getCurrentUser();
        String userId = user.getYhtUserId();
        String limitChildTenantId = user.getYhtTenantId();
        Iterator var6 = bills.iterator();

        while(var6.hasNext()) {
            BizObject bill = (BizObject)var6.next();
            String businessKey = billContext.getBillnum() + "_" + bill.get("id");
            JsonNode responseNode = (JsonNode)this.bpmRestServices(billContext, userId, limitChildTenantId, user.getOrgId()).getRuntimeService().withDrawFormUseBusinessKey(businessKey, (String)null, (String)null, (String)null, false);
            this.handleResult(responseNode);
        }

    }

    public boolean bpmControl(BillContext billContext, BizObject bill) throws Exception {
        return this.existsProcessDefinition(billContext, bill);
    }

    private String getTransactionType(BillContext billContext, BizObject bill) throws Exception {
        Map billBaseMap = this.billMetaBiz.getBaseBill(billContext.getBillnum(), AppContext.getTenantId());
        String label;
        if (MapUtils.isNotEmpty(billBaseMap) && billBaseMap.containsKey("label") && billBaseMap.get("label") != null) {
            label = (String)billBaseMap.get("label");
            if (label.contains("ignoreTransaction")) {
                return "";
            }
        }

        label = MetaAttributeUtils.getFieldByAttributeOrName(billContext.getFullname(), "isTransactionType", "bustype");
        return null == bill.get(label) ? "" : "" + bill.get(label);
    }

    private String getCode(BillContext billContext, BizObject bill) throws Exception {
        String codeField = com.yonyou.ucf.mdd.core.utils.MetaAttributeUtils.getAttributeField(billContext.getFullname(), "isCode", "code");
        String codeVaue = bill.get(codeField) != null ? (String)bill.get(codeField) : "";
        String code = billContext.getName() + "" + codeVaue;
        return code;
    }

    private String getMasterOrg(BillContext billContext, BizObject bill) throws Exception {
        String orgField = MetaAttributeUtils.getFieldByAttributeOrName(billContext.getFullname(), "isMasterOrg", "org");
        String org = "" + bill.get(orgField);
        return org;
    }

    private String getBillTypeId(BillContext billContext) throws Exception {
        String billTypeId = null;
        if (null != billContext) {
            String subId = Toolkit.isEmpty(this.billtypeSubid) ? billContext.getSubid() : this.billtypeSubid;
            billTypeId = subId + "." + billContext.getBillnum();
            IProcessExService processExService = (IProcessExService)AppContext.getBean(IProcessExService.class);
            if (null != processExService) {
                billTypeId = processExService.getBillTypeId(subId, billContext.getBillnum(), billContext);
            }
        }

        return billTypeId;
    }

    public boolean existsProcessDefinition(BillContext billContext, BizObject bill) throws Exception {
        String transactionType = this.getTransactionType(billContext, bill);
        List<RestVariable> taskVariables = this.prepareVariables(bill);
        LoginUser user = AppContext.getCurrentUser();
        logger.info(String.format("审批流支持日志 : YhtUserId: %s , YhtTenantId: %s , TenantId: %s ", user.getYhtUserId(), user.getYhtTenantId(), AppContext.getTenantId()));
        String result = this.queryProcessDefinition4save(billContext, user.getYhtUserId(), user.getYhtTenantId(), transactionType, user.getOrgId(), taskVariables);
        return null != result;
    }

    public String queryProcessDefinition(BillContext billContext, String userId, String limitChildTenantId, String categoryId, String org, List<RestVariable> taskVariables) throws Exception {
        ProcessDefinitionQueryParam processDefinitionQueryParam = new ProcessDefinitionQueryParam();
        processDefinitionQueryParam.setCategory(categoryId);
        if (null != billContext) {
            String subId = Toolkit.isEmpty(this.billtypeSubid) ? billContext.getSubid() : this.billtypeSubid;
            String billTypeId = subId + "." + billContext.getBillnum();
            IProcessExService processExService = (IProcessExService)AppContext.getBean(IProcessExService.class);
            if (null != processExService) {
                billTypeId = processExService.getBillTypeId(subId, billContext.getBillnum(), billContext);
            }

            processDefinitionQueryParam.setBillTypeId(billTypeId);
        }

        processDefinitionQueryParam.setLatest(true);
        processDefinitionQueryParam.setCascadeOrg(true);
        processDefinitionQueryParam.setTaskVariables(taskVariables);
        if (logger.isInfoEnabled()) {
            logger.info("审批流支持日志 : processDefinitionQueryParam:{}", GsonHelper.ToJSon(processDefinitionQueryParam));
        }

        JsonNode responseNode = (JsonNode)this.bpmRestServices(billContext, userId, limitChildTenantId, org).getRepositoryService().queryProcessDefinitionInAuthorityWithCondition(processDefinitionQueryParam);
        return this.handleResult(responseNode);
    }

    public String queryProcessDefinition4save(BillContext billContext, String userId, String limitChildTenantId, String categoryId, String org, List<RestVariable> taskVariables) throws Exception {
        ProcessDefinitionQueryParam processDefinitionQueryParam = new ProcessDefinitionQueryParam();
        String billTypeId = this.getBillTypeId(billContext);
        processDefinitionQueryParam.setBillTypeId(billTypeId);
        processDefinitionQueryParam.setCategory(categoryId);
        RepositoryService repositoryService = this.bpmRestServices(billContext, userId, limitChildTenantId, org).getRepositoryService();
        JsonNode responseNode = (JsonNode)repositoryService.queryProcessDefinition(processDefinitionQueryParam);
        Integer total = responseNode.get("total") == null ? 0 : Integer.valueOf(responseNode.get("total") + "");
        return total != null && total > 0 ? responseNode.toString() : null;
    }

    public Map<String, Object> assignCheck(BillContext billContext, BizObject bill) throws Exception {
        String categoryId = this.getTransactionType(billContext, bill);
        String limitTenantId = AppContext.getCurrentUser().getYhtTenantId();
        String yhtUserId = AppContext.getCurrentUser().getYhtUserId();
        String billTypeId = this.getBillTypeId(billContext);
        String org = this.getMasterOrg(billContext, bill);
        RuntimeService rt = this.bpmRestServices(yhtUserId, limitTenantId, org).getRuntimeService();
        AssignCheckParam parm = new AssignCheckParam();
        parm.setJudgeAssemble(true);
        parm.setUseStartConditionInDetailCategory(true);
        parm.setCategory(categoryId);
        parm.setBillTypeId(billTypeId);
        ViewModel cardSimpleVM = this.getCardSimpleVM(billContext);
        BizObject formatBill = bill;
        if (cardSimpleVM != null) {
            IBillFormatService iBillFormatService = (IBillFormatService)AppContext.getBean("billFormatServiceImpl", IBillFormatService.class);
            if (null != iBillFormatService) {
                formatBill = iBillFormatService.formatBillData(bill, cardSimpleVM, this.getMainEntity(cardSimpleVM));
            }
        } else {
            logger.error("格式化处理流程参数 异常， viewmodel 为空");
        }

        List<RestVariable> taskVariables = this.prepareVariables(formatBill);
        parm.setTaskVariables(taskVariables);
        if (logger.isInfoEnabled()) {
            logger.info("RuntimeService Params : " + GsonHelper.ToJSon(rt.getBaseParam()));
            logger.info("assignCheck Params : " + GsonHelper.ToJSon(parm));
        }

        JsonNode node = (JsonNode)rt.assignCheck(parm);
        if (null != node && logger.isDebugEnabled()) {
            logger.debug("assignCheck 返回结果： " + node.toString());
        }

        Map<String, Object> map = (Map)(new ObjectMapper()).convertValue(node, Map.class);
        return map;
    }
}
